#ifndef _AnimatorClock_H_
#define _AnimatorClock_H_

#include "../../includes/includes.h"

//=============================================================================
/** This is a base for all animations to be performed by
	an Animator.

	An aniation has some identifiers which are used in various ways.
	The 'type name' is used to define a category of animation
	(e.g. colour, position, size, etc..). The 'name' is used as an 
	ID to identify a specific animation within that category. When
	an animation is started, if the typename and name both match an 
	existing animation for that target, that animation will be 
	replaced with the new one.

	A void* is used to identify the target in order to allow the
	system to be applied to any target class (not just for components).
	It's designed to allow for a modular 'building block' design of
	animtions; for example, an animation that simply modifies a pair
	of values over time could be used as a base for both 'size' and
	'position' animations.
	
	To use this base, use the constructor (defining any required
	parameters for the animation) to initialise your animation,
	and implement 'useTimeSlice(int)' to define the response to
	each time-step (the parameter provides the number of millisecs
	since the last step).

	See the 'TimeBasedAnimation' subclass for a handy alternative
	base (which takes care of converting the elapsed time into a
	progress parameter for simplified use).	*/
class Animation
{
public:

	Animation (void* animTarget, const String& animName, const String& animationTypeName);
	virtual ~Animation ();

	/** Returns the target for this Animation.*/
	void* getTarget ();
	/** Get this Animation's type name. */
	String getTypeName () const;
	/** Get this Animation's specific name. */
	String getName () const;

	/** This should be defined to respond to the passing
		of time. If the animation is to continue after this
		call, return true; return false to signal that the
		animation is finished and can be stopped.*/
	virtual bool useTimeSlice (const int elapsed) = 0;

	/** This should be defined to skip the animation to
		its end state. */
	virtual void skipToEnd () = 0;
	/** This should be defined to reset the animation to
		its starting state. */
	virtual void resetToStart () = 0;

	/** Find out if this animation is currently running. */
	bool isRunning ();

	friend class Animator;

private:
	
	String typeName;
	String name;
	bool running;
	void* target;
};

//=============================================================================
/** One of these can be used to initiate animations for a
	number of targets. Simply create a new instance of an
	Animation subclass, and call 'start' with it.
	You might want to subclass this and provide functions
	to take care of creating the Animations and starting
	them, to make for a simpler interface.
	
	For reference, internally the animations are all
	grouped by target. Each step, the animator advances
	all the animations for each target in turn, calling
	frameFinished() before moving onto the next one. This
	allows you to put any refresh code (e.g. repaint())
	at the end of the whole frame for a target, rather
	than at the end of each individual animation (which
	would potentially cause multiple calls). */
class Animator
{
public:

	Animator ();
	virtual ~Animator ();

	/** Pauses all animations (disconnects the clock).*/
	void pauseAll ();
	/** Resumes all animations (by reconnecting the clock).*/
	void resumeAll ();
	/** Stops all animations. */
	void stopAll (bool skipToEndOfAnimations);

	/** This is used by the clock to advance all currently
		playing animations. */
	bool useTimeSlice (int elapsedMs);

	/** Call this to start a new animation. Simply create
		a new instance of the desired Animation subclass,
		and pass it in here. It will be destroyed automatically
		when it is finished. */
	void start (Animation* anim);
	/** If you know the identifiers for a particular animation,
		you can stop it with them here. It requires the target,
		the animation type name and the specific animation name. */
	void stop (void* target, const String& typeName, const String& name, bool skipToEnd);

	/** This function is called when every animation for a
		particular target has finished the current frame.
		For example, if your Animator is designed to animate
		multiple parameters within the paint function of a 
		Component, it's best to have a single call to repaint()
		once all parameters have been updated [rather than
		call repaint() from each Animation]. */
	virtual void frameFinished (void* target);

private:

	void connectToClock ();
	void disconnectFromClock ();

	VoidArray targetAnimators;
};

//=============================================================================
/** This is a master singleton clock, used to drive all Animator
	objects used in a program. 
	
	You don't need to do anything with it, but it's available 
	(using the usual singleton access 'getInstance()' static 
	method) as you may wish to specify a specific timer interval 
	[it's driven by a timer, and so carries with it the same 
	resolution limitations]. */
class AnimatorClock	:	private Timer,
						public DeletedAtShutdown
{
public:

	AnimatorClock ();
	~AnimatorClock ();

	/** This specifies the timer interval used by the
		master clock. Set it higher to reduce the frame
		rate (and thus free up a bit of CPU). */
	void setTimerInterval (int ms);
	int getTimerInterval ();

	void connectAnimator (Animator* animator);
	void disconnectAnimator (Animator* animator);
	void disconnectAllAnimators ();

	void start ();
	void stop ();

	int getNumAnimatorsRegistered ();
	Animator* getRegisteredAnimator (int index);

	juce_DeclareSingleton (AnimatorClock, true);

private:

	void timerCallback ();

	Array<Animator*, CriticalSection> animators;
	int timerInterval;

	Time prevTime;
	bool running;
};



#endif//_AnimatorClock_H_
